/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.task.zkex.list.boost;

import cn.easyplatform.EasyPlatformWithLabelKeyException;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.vos.datalist.ListGroupVo;
import cn.easyplatform.messages.vos.datalist.ListHeaderVo;
import cn.easyplatform.type.DeviceType;
import cn.easyplatform.type.ListRowVo;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.dialog.MessageBox;
import cn.easyplatform.web.ext.zul.Datalist;
import cn.easyplatform.web.task.OperableHandler;
import cn.easyplatform.web.task.BackendException;
import cn.easyplatform.web.task.support.SupportFactory;
import cn.easyplatform.web.task.zkex.list.GroupableListSupport;
import cn.easyplatform.web.task.zkex.list.exporter.AbstractExporter;
import cn.easyplatform.web.task.zkex.list.group.Group;
import cn.easyplatform.web.task.zkex.list.group.ReportGroup;
import cn.easyplatform.web.task.zkex.list.group.ResultHelper;
import cn.easyplatform.web.task.zkex.list.menu.ColumnMenu;
import cn.easyplatform.web.task.zkex.list.menu.GroupColumnMenu;
import cn.easyplatform.web.task.zkex.list.menu.SimpleColumnMenu;
import org.apache.commons.lang3.math.NumberUtils;
import org.zkoss.lang.Objects;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zul.Columns;
import org.zkoss.zul.Menuitem;
import org.zkoss.zul.Menupopup;
import org.zkoss.zul.West;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class ReportBoostBuilder extends AbstractBoostBuilder implements
        GroupableListSupport {

    private List<ReportGroup> groups;

    private ReportGroup group;

    private int showLevel;

    private List<ListRowVo> data;

    public ReportBoostBuilder(OperableHandler mainTaskHandler, Datalist entity, Component anchor) {
        super(mainTaskHandler, entity, anchor);
    }

    @Override
    protected Component createContent() {
        getEntity().setEditableColumns(null);
        if (getEntity().getPageSize() > 0 && getEntity().isShowPaging()) {
            listExt.setMold("paging");
            listExt.setPageSize(getEntity().getPageSize());
            listExt.getPaginal().setPageSize(listExt.getPageSize());
            paging = listExt.getPagingChild();
            paging.setAutohide(getEntity().isPagingAutohide());
            paging.setDetailed(getEntity().isPagingDetailed());
            if (getEntity().getPagingMold() != null)
                paging.setMold(getEntity().getPagingMold());
            if (getEntity().getPagingStyle() != null)
                paging.setStyle(getEntity().getPagingStyle());
        }
        return super.createContent();
    }

    @Override
    protected void createHeader() {
        groups = null;
        groups = new ArrayList<ReportGroup>();
        if (layout.getGroups().isEmpty()) {
            ListGroupVo gv = new ListGroupVo();
            gv.setFields(new String[0]);
            group = ReportGroup.cast(this, expressionEngine, gv, layout);
            groups.add(group);
        } else {
            for (ListGroupVo gv : layout.getGroups()) {
                ReportGroup g = ReportGroup.cast(this, expressionEngine, gv, layout);
                if (Objects.equals(getEntity().getGroup(), g.getName()))// 选择默认的分组，由<datalist
                    // group="xx"/>
                    group = g;
                groups.add(g);
            }
            if (group == null)// 如果没有默认的分组，选择第1个
                group = groups.get(0);
            showLevel = group.getMaxLevel();
        }
        if (!Strings.isBlank(layout.getOnRow()))
            expressionEngine = SupportFactory.getExpressionEngine(this,
                    layout.getOnRow());
        super.createHeader();
        group.getRoot().setParent(listExt);
    }

    @Override
    protected void buildGroup(ListHeaderVo hv, int index) {
        if (group.getMaxLevel() > 0) {
            for (Group g : groups)
                g.addTotal(hv.getTotalType(), index);
        }
    }

    @Override
    protected void redraw(List<ListRowVo> rowset) {
        this.data = rowset;
        try {
            if (expressionEngine != null)
                expressionEngine.compile();
            Map<String, Object> evalMap = new HashMap<String, Object>();
            Map<String, Component> managedComponents = new HashMap<String, Component>();
            ResultHelper rh = new ResultHelper(rowset);
            while (rh.hasNext()) {
                rh.next();
                evalMap.clear();
                managedComponents.clear();
                group.createGroup(rh, evalMap, managedComponents, showLevel + 1);
            }
            if (getEntity().getPageSize() > 0)
                listExt.getPagingChild().setTotalSize(
                        listExt.getRows().getChildren().size());
            evalMap = null;
            managedComponents = null;
        } finally {
            if (expressionEngine != null)
                expressionEngine.destroy();
        }
    }

    @Override
    public void onEvent(Event event) throws Exception {
        try {
            if (event.getTarget() instanceof Menuitem) {
                String id = (String) event.getTarget().getAttribute("id");
                id = id == null ? "" : id;
                if (id.equals("--exp--")) {
                    AbstractExporter.createExporter(mainTaskHandler, this)
                            .doExport();
                } else if (id.equals("--filter--")) {
                    ColumnMenu menu = (ColumnMenu) event.getTarget()
                            .getParent();
                    filter(menu.getHeader());
                } else if (id.startsWith("group_")) {
                    if (id.endsWith("user")) {// 用户自定义

                    } else {
                        int index = NumberUtils.toInt(id.substring(6));
                        group = groups.get(index);
                        listExt.getRows().detach();
                        group.getRoot().setParent(listExt);
                        showLevel = group.getMaxLevel();
                        clear();
                        redraw(data);
                        List<Component> mp = event.getTarget().getParent()
                                .getChildren();
                        for (Component comp : mp) {
                            if (comp != event.getTarget()
                                    && comp instanceof Menuitem)
                                ((Menuitem) comp).setChecked(false);
                        }
                    }
                } else if (id.startsWith("show_")) {
                    showLevel = NumberUtils.toInt(id.substring(5));
                    clear();
                    redraw(data);
                    List<Menuitem> mp = event.getTarget().getParent()
                            .getChildren();
                    for (Menuitem comp : mp) {
                        if (comp != event.getTarget())
                            comp.setChecked(false);
                    }
                }
            } else super.onEvent(event);
        } catch (EasyPlatformWithLabelKeyException ex) {
            MessageBox.showMessage(ex);
        } catch (BackendException ex) {
            MessageBox.showMessage(ex.getMsg().getCode(), (String) ex.getMsg()
                    .getBody());
        }
    }

    @Override
    protected void setMenupopup(HtmlBasedComponent head) {
        if (Contexts.getEnv().getDeviceType().equalsIgnoreCase(DeviceType.AJAX.getName())) {
            Component layout = listExt.getParent().getParent();
            West west = new West();
            west.setBorder("none");
            west.setSize("0");
            west.setCollapsible(false);
            layout.appendChild(west);
            Menupopup popup = null;
            if (group.getMaxLevel() == 0)
                popup = new SimpleColumnMenu(head, this, getEntity().isExport(),
                        getEntity().isPrint());
            else
                popup = new GroupColumnMenu((Columns) head, this);
            popup.setId(listExt.getId() + "_popup");
            west.appendChild(popup);
            ((Columns) head).setMenupopup(popup.getId());
        }
    }

    @Override
    public void clear() {
        for (Group g : groups)
            g.clear();
    }

    @Override
    public List<ReportGroup> getGroups() {
        return groups;
    }

    @Override
    public ReportGroup getGroup() {
        return group;
    }
}
